package model.parseTree;

import model.searchers.ISearcher;
import model.searchers.URLList;

/**
 * Class AndNode represents a special type of node in a syntax tree. It is used
 * to represent the boolean operator conjunction. It keeps track of its children.
 * The result of evaluating an object of class AndNode is the intersection of results obtained by 
 * evaluating the left and right subtrees.
 */
public class AndNode extends SearchNode {

	/**
	 * Constructor of AndNode. Creates a search node with value "AND" and the specified child nodes.
	 * 
	 * @param leftChild		left child node
	 * @param rightChild	right child node
	 */
	public AndNode(SearchNode leftChild, SearchNode rightChild) {
		super(leftChild, rightChild, "AND");
	}

	/**
	 * Returns the resulting list of URLs containing only the URLs that are
	 * results of both search on right subquery (subtree) and left subquery
	 * (subtree)
	 * 
	 * @param searcher	the searcher to perform the search for the URLs
	 * @return list of results of AND-search
	 */
	@Override
	public URLList getResult(ISearcher searcher) {
		// find results of left and right subtrees
		URLList startLeftResult = (getLeft() == null) ? null : getLeft()
				.getResult(searcher);
		URLList currentLeft = startLeftResult;
		URLList startRightResult = (getRight() == null) ? null : getRight()
				.getResult(searcher);
		URLList currentRight = startRightResult;
		URLList result = null;

		// get all combinations of URLList objects in each of the results
		while (currentLeft != null) {
			while (currentRight != null) {
				// if two result elements agree on a url, both words are on the page
				//number of occurrences is set to number of times the pair of words is found
				if (currentLeft.getValue().equals(currentRight.getValue())) {
					URLList match = new URLList(currentLeft.getValue(),
							min(currentRight.getOccurrences(), currentLeft.getOccurrences()), result);
					result = match;
				}
				currentRight = (URLList) currentRight.getNext();
			}
			currentLeft = (URLList) currentLeft.getNext();
			currentRight = startRightResult;
		}
		return result;
	}
	
	/**
	 * Returns the minimum of integers a and b. If they are equal, a is returned
	 * 
	 * @param a 	an integer
	 * @param b		an integer
	 * @return 		the least of a and b
	 */
	private int min(int a, int b) {
		int minimum;
		if (a <= b)
			minimum = a;
		else
			minimum = b;
		return minimum;
	}

}
